import ymlLoad from "@i18n.addon/yml/ymlLoad.js"
import ymlDump from "@i18n.addon/yml/ymlDump.js"

const _json = "_.json",
	BLOG = "Blog",
	DOC = "Doc"

export const USE = {}

const _tree = (li, stack) => {
	let [depth, nowli] = stack.at(-1)

	while (li.length) {
		const [d, o] = li.shift()
		if (d == depth) {
			nowli.push(o)
		} else if (d > depth) {
			const t = [o],
				len = nowli.length - 1
			nowli[len] = [nowli[len], t]
			stack.push([d, t])
			_tree(li, stack)
			;[depth, nowli] = stack.at(-1)
		} else {
			while (d < depth) {
				stack.pop()
				;[depth, nowli] = stack.at(-1)
			}
			nowli.push(o)
			return
		}
	}
}

const tree = (li) => {
	const root = []
	_tree(li, [[0, root]])
	return root
}

const strLi = (s) => {
	const r = [],
		stack = []
	for (const i of s.split("\n")) {
		if (i) {
			const t = i.trimStart()
			if (t.startsWith("#")) {
				continue
			}
			const indent = i.length - t.length

			if (stack.length == 0) {
				stack.push(indent)
			} else if (indent > stack.at(-1)) {
				stack.push(indent)
			} else {
				while (indent < stack.at(-1)) {
					stack.pop()
				}
			}
			r.push([t, stack.length - 1])
		}
	}
	return r
}

const extract = (url, txt) => {
	let title,
		pos = 0,
		meta

	const li = txt.split("\n")
	if (li[0] == "---") {
		meta = []
		li.shift()
		while (li.length && li[0] != "---") {
			meta.push(li.shift())
		}
	}

	for (const i of li) {
		++pos
		if (i.startsWith("<h1")) {
			let t = [],
				h1pos = pos - 1,
				p
			while (h1pos < li.length) {
				const line = li[h1pos++]
				p = line.indexOf("</h1>")
				if (~p) {
					t.push(line.slice(0, p))
					break
				}
				t.push(line)
			}
			t = t.join("\n").slice(3)
			p = t.indexOf(">")
			if (~p) {
				title = t
					.slice(p + 1)
					.replace(/<[^<]+>/g, "")
					.trim()
				if (title) {
					pos = h1pos
					break
				}
			}
		}
		if (i.startsWith("#")) {
			const p = i.indexOf(" ")
			if (p > 0) {
				title = i.slice(p + 1)
				break
			}
		}
	}

	if (!title) {
		return
	}
	if (
		// has more (章节本身是否可以点击)
		li.slice(pos).join("\n").trim() ? 1 : 0
	) {
		const pos = url.lastIndexOf(".")
		if (~pos) {
			url = url.slice(0, pos)
		}
		if (url.endsWith("/README")) {
			url = url.slice(0, -7)
		} else if (url == "README") {
			url = ""
		}
		return [meta, [title, url]]
	}
	return [meta, title]
}

export const gen = (root, url, lang_li, file, gen_arg, meta, wrap) => {
	if (url != "/") {
		url = `/${url}/`
	}
	let toc
	try {
		const fp = root + lang_li[0] + url + "TOC"
		toc = rStr(fp)
	} catch (e) {
		console.error(e)
		return
	}
	toc = strLi(toc)
	if (toc.length > 0) {
		for (const lang of lang_li) {
			const toc_li = [],
				dir = `${lang}${url}`
			for (const [fp, indent] of toc) {
				let txt
				try {
					txt = rStr(root + dir + fp).trim()
				} catch (e) {
					console.error(e)
					continue
				}
				const po = extract(fp, txt)
				if (po) {
					if (meta && Array.isArray(po[1])) {
						meta(po, txt, fp)
					}
					toc_li.push([indent, po[1]])
				}
			}
			let val
			try {
				val = tree(toc_li.slice(), 0, [])
			} catch (e) {
				for (const i of toc_li) {
					console.error(JSON.stringify(i))
				}
				console.error("\n" + fp + "\n", e)
				return
			}
			val.unshift(url.slice(1, -1))

			if (wrap) {
				val = wrap(lang, val)
			}
			// if (lang == "zh") {
			// 	console.log(JSON.stringify(val, null, 2))
			// }
			file.push([dir + _json, JSON.stringify(val)])
			if (gen_arg) gen_arg(lang, toc_li)
		}
	}
	return toc
}

USE[DOC] = gen
USE[BLOG] = (root, url, lang_li, file, gen_arg) => {
	let ts,
		pts,
		exist = new Set(),
		has_new
	const tsfp = root + ".i18n/data/blog/" + url + ".yml",
		now = Number.parseInt(new Date() / 1000),
		li = [],
		author_map = new Map(),
		fp_author = new Map()
	try {
		pts = ymlLoad(rStr(tsfp))
	} catch {}
	pts = pts || {}

	gen(
		root,
		url,
		lang_li,
		file,
		gen_arg,
		([meta, li], txt, fp) => {
			if (!meta) {
				return
			}
			let author = fp_author.get(fp)
			if (author === undefined) {
				meta = meta.join("\n")
				try {
					meta = ymlLoad(meta) || {}
				} catch (err) {
					console.error(fp, "yaml parse error", err, "\n" + meta)
					fp_author.set(fp, 0)
					return
				}
				author = meta.author
				if (author) {
					if (!author_map.has(author)) {
						const { size } = author_map
						author_map.set(size, author)
						author = size
					}
				} else {
					author = -1
				}
				fp_author.set(fp, author)
			}

			const url = li[1]
			exist.add(url)
			let ts = pts[url]
			if (ts == undefined) {
				ts = Number.parseInt(new Date() / 1000)
				pts[url] = ts
				has_new = 1
			}
			li.push(ts)
			li.push(author)
		},
		(lang, val) => {
			const author_yml_fp = root + lang + "/author.yml"
			let author_yml
			try {
				author_yml = rStr(author_yml_fp)
			} catch (e) {
				author_yml = ""
			}
			try {
				author_yml = ymlLoad(author_yml) || {}
			} catch (e) {
				author_yml = {}
				console.error(author_yml_fp, e)
			}
			const author_li = []
			for (const [p, id] of author_map.entries()) {
				const meta = author_yml[id]
				if (meta) {
					author_li[p] = [meta.name || id, meta.title || 0, meta.url || 0]
				} else {
					author_li[p] = [id]
				}
			}
			val.unshift(author_li)
			return val
		},
	)

	if (has_new || exist.size != Object.keys(pts).length) {
		const dump = {}
		for (const url of exist) {
			dump[url] = pts[url]
		}
		wPath(tsfp, ymlDump(dump))
	}
}

export default ({ root, lang_li }) => {
	root = root + "/"
	const nav = ymlLoad(rStr(root + ".i18n/conf.yml")).nav
	const file = []
	for (let { use, url, i18n, menu } of nav) {
		url = url || i18n
		const gen = USE[use]
		if (gen) {
			if (menu) {
				let arg
				const p = menu.indexOf(" ")
				if (~p) {
					arg = menu.slice(p + 1).trim()
				}
				if (arg) {
					const arg_title_li = {}
					for (let i of arg.split(",")) {
						i = i.trim()
						gen(root, i, lang_li, file, (lang, toc_li) => {
							if (!Array.isArray(toc_li[0])) {
								return
							}
							let title = toc_li[0][1]
							if (Array.isArray(title)) {
								// "i18 : 命令行 markdown & yml 翻译工具" # no more
								// ["i18n.site : 多语言纯静态网站(文档)框架","/doc/i18n.site"] # has more
								title = title[0]
							}
							if (!arg_title_li[lang]) {
								arg_title_li[lang] = []
							}
							arg_title_li[lang].push(title)
						})
					}
					for (const lang in arg_title_li) {
						file.push([
							lang +
								(url ? (url.startsWith("/") ? url : "/" + url) : "") +
								"/" +
								_json,
							JSON.stringify(arg_title_li[lang]),
						])
					}
					continue
				}
			}
			gen(root, url, lang_li, file)
		}
	}
	// for (const i of file) {
	// 	if (i[0].startsWith("zh")) {
	// 		console.log(JSON.stringify(i))
	// 	}
	// }
	return { file }
}
